#include "mainwidget.h"
#include "ui_mainwidget.h"
#include <QFileDialog>
#include <QDebug>

MainWidget::MainWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MainWidget)
{
    ui->setupUi(this);
    basePath = qApp->applicationDirPath();
    pathPos = new QCPCurve(ui->map->xAxis, ui->map->yAxis);
    curGraph = NULL;
    pressed = false;
    insertIndex = -1;
    optFlag = 0;
    moveIndex = -1;
    ui->func->hide();
    ui->map->setInteractions(QCP::iRangeZoom | QCP::iRangeDrag | QCP::iMultiSelect);
    ui->map->setSelectionTolerance(15);
//    connect(ui->map, SIGNAL(selectionChangedByUser()), this, SLOT(selectPointChanged()));
    connect(ui->map, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(m_press(QMouseEvent*)));
    connect(ui->map, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(m_move(QMouseEvent*)));
    connect(ui->map, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(m_release(QMouseEvent*)));
}

MainWidget::~MainWidget()
{
    delete ui;
}

void MainWidget::on_open_clicked()
{
    QFileDialog dir;
    dir.setWindowFlags(Qt::WindowStaysOnTopHint);
    QString fileName = dir.getOpenFileName(NULL, "请打开地图文件", basePath);
    if(fileName.isNull())
        return;

    listParams.clear();
    if(!listPoint.isEmpty())
    {
        listPoint.clear();
        listPoint.squeeze();
    }

    filePath = fileName;
    listPoint = readCoors(fileName);

    if(listPoint.isEmpty())
        return;
    paintPoints(listPoint);
}

void MainWidget::on_save_clicked()
{
    QFile f(filePath+".bs");
    if(!f.open(QFile::WriteOnly))
        return;
    int i=0;

    foreach(QPointF p, listPoint)
    {
        if(i>(listParams.count()-1))
            i=listParams.count()-1;
        if(listParams.at(i).right(1) != "\n")
            f.write((QString("%1 %2 %3\n").arg(QString::number(p.x(),'f')).arg(QString::number(p.y(),'f')).arg(listParams.at(i++))).toLocal8Bit());
        else
            f.write((QString("%1 %2 %3").arg(QString::number(p.x(),'f')).arg(QString::number(p.y(),'f')).arg(listParams.at(i++))).toLocal8Bit());
    }
    f.close();
}

void MainWidget::m_press(QMouseEvent* e)
{
    if(optFlag == 0)
    {
        if(e->button() == Qt::LeftButton)
        {
            moveIndex = findPoint(e->localPos(),listPoint,15);
            insertIndex = moveIndex;
            qDebug()<<moveIndex;
            ui->index->setText(QString::number(moveIndex));
            if(moveIndex < 0)
                return;

            ui->map->setInteractions(QCP::iRangeZoom | QCP::iMultiSelect);
        }
        else if(e->button() == Qt::RightButton)
        {
//            qDebug()<<"[insert start]";
            pressed = true;
            ui->map->setInteractions(QCP::iRangeZoom | QCP::iMultiSelect);
        }
    }
    else if(optFlag == 1)
    {

    }
}

void MainWidget::m_move(QMouseEvent *e)
{
    if(optFlag == 0)
    {
        if(!pressed)
        {
            if(moveIndex<0)
                return;
            QPointF p = pixToMap(e->localPos());
            //    qDebug()<<p;
            listPoint.removeAt(moveIndex);
            //    curGraph->data()->remove(listPoint[moveIndex].x());
            //    curGraph->data()->add(QCPGraphData(p.x(),p.y()));
            listPoint.insert(moveIndex, p);
            setData(listPoint);
            ui->map->replot();
        }
        else if(pressed && (insertIndex>=0))
        {
//            qDebug()<<"[insert]"<<pixToMap(e->localPos());
//            listPoint.insert(insertIndex, pixToMap(e->localPos()));
//            setData(listPoint);
//            ui->map->replot();
        }
    }
    else if(optFlag == 1)
    {

    }
}

void MainWidget::m_release(QMouseEvent* e)
{
    if(optFlag == 0)
    {
        if(e->button() == Qt::RightButton)
        {
            if(insertIndex == -1)
                return;
            qDebug()<<"[insert]"<<pixToMap(e->localPos());
            listPoint.insert(insertIndex, pixToMap(e->localPos()));
            setData(listPoint);
            ui->map->replot();
//            qDebug()<<"[insert finish]";
            pressed = false;
            ui->map->setInteractions(QCP::iRangeZoom | QCP::iRangeDrag | QCP::iMultiSelect);
        }
        else
        {
            moveIndex = -1;
            ui->map->setInteractions(QCP::iRangeZoom | QCP::iRangeDrag | QCP::iMultiSelect);
        }
    }
    else if(optFlag == 1)
    {

    }
}


QVector<QPointF> MainWidget::readCoors(QString fileName)
{
    qDebug()<<"readPathPoint"<<fileName;
    if(fileName.isEmpty())
        return QVector<QPointF>();

    QFile f(fileName);
    if(f.open(QFile::ReadOnly))
        qDebug()<<"file open success.";
    else
        return QVector<QPointF>();

    QVector<QPointF> list_path;
    QByteArray qba;

    while(!(qba = f.readLine()).isEmpty())
    {
        QString str = QString(qba);
        QStringList l = str.split(" ", QString::SkipEmptyParts);
        if(l.count() < 2)
        {
            qDebug()<<"[readPoint]:File fomat error.";
            continue;
        }
        bool ok;
        QPointF p;
        p.setX(l.at(0).toDouble(&ok));
        if(!ok)
        {
            qDebug()<<"[readPoint]:File fomat error.";
            return QVector<QPointF>();
        }
        p.setY(l.at(1).toDouble(&ok));
        if(!ok)
        {
            qDebug()<<"[readPoint]:File fomat error.";
            return QVector<QPointF>();
        }
        qDebug()<<p;
        list_path.push_back(p);

        listParams<<l.mid(2,l.count()-2).join(' ');
    }
    f.close();
    return list_path;
}

void MainWidget::paintPoints(QVector<QPointF> points)
{
    if(curGraph != NULL)
        curGraph->deleteLater();

    ui->map->clearGraphs();
    ui->map->addGraph(ui->map->yAxis, ui->map->xAxis);

    pathPos->setPen(QPen(QBrush(QColor(50,150,50)), 1));

    QPen drawPen;
    drawPen.setColor(Qt::green);
    drawPen.setWidth(4);
    curGraph = ui->map->addGraph();
    curGraph->setSelectable(QCP::stMultipleDataRanges);
    curGraph->setPen(drawPen);
    curGraph->setLineStyle(QCPGraph::lsNone);
    curGraph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 2));
    ui->map->xAxis->setVisible(true);
    ui->map->yAxis->setVisible(true);
    setData(points);
    setCurve(points);
    ui->map->rescaleAxes();
    ui->map->replot();
}

void MainWidget::setData(QVector<QPointF> points)
{
    if(points.isEmpty())
        return;

    QVector<double> x,y;
    QPointF p;
//    qDebug()<<points.count();
    foreach(p, points)
    {
//        qDebug()<<p;
        x.push_back(p.x());
        y.push_back(p.y());
    }
    if(curGraph == NULL)
        return;

//    qDebug()<<x<<y;
    curGraph->setData(x,y);
}

void MainWidget::setCurve(QVector<QPointF> l)
{
    if(l.isEmpty())
        return;

    qDebug()<<"[setCurve]"<<l.count();
    QVector<double> x,y;
    QPointF p;

    foreach(p, l)
    {
        x.push_back(p.x());
        y.push_back(p.y());
    }
    if(pathPos == NULL)
        return;

    pathPos->setData(x,y);
}

QPoint MainWidget::mapToPix(QPointF p)
{
    return QPoint(ui->map->xAxis->coordToPixel(p.x()), ui->map->yAxis->coordToPixel(p.y()));
}

QPointF MainWidget::pixToMap(QPointF p)
{
    return QPointF(ui->map->xAxis->pixelToCoord(p.x()), ui->map->yAxis->pixelToCoord(p.y()));
}

QVector<QPointF> MainWidget::listDiv(QVector<QPointF> l, int step)
{
    QVector<QPointF> ret;
    int i = 0;
    qDebug()<<"div step"<<step;

    foreach(QPointF p, l)
        if(!((i++)%step))
            ret.push_back(p);

    return ret;
}

QVector<QPointF> MainWidget::listInsert(QVector<QPointF> l, int step)
{
    BSpline b_spline;
    return b_spline.generateCurve(l, 3, 1.0/step);
}

int MainWidget::findPoint(QPointF p,QVector<QPointF> l, int range)
{
    int i=0;
    foreach(QPointF t, l)
    {
        if((p-mapToPix(t)).manhattanLength()<range)
            return i;
        i++;
    }
    return -1;
}

void MainWidget::on_add_clicked()
{
    bool ok;
    int step = ui->step->text().toInt(&ok);
    if(!ok)
        return;

    qDebug()<<"[add before]"<<listPoint.count();
    listPoint = listInsert(listPoint,step);
    qDebug()<<"[add after]"<<listPoint.count();
    setData(listPoint);
    ui->map->replot();
}

void MainWidget::on_div_clicked()
{
    bool ok;
    int step = ui->step->text().toInt(&ok);
    if(!ok)
        return;

    qDebug()<<"[div before]"<<listPoint.count();
    listPoint = listDiv(listPoint,step);
    qDebug()<<"[div after]"<<listPoint.count();
    setData(listPoint);
    ui->map->replot();
}

void MainWidget::on_mov_clicked()
{
    optFlag = 0;
}

void MainWidget::on_del_clicked()
{
    optFlag = 1;
}
